///////////////////////////////////////////////////
// File Name: switch_top_v1_tb.v
// Author: zeping fan
// mail:   zpfan007@163.com
// Created Time: 2023年06月29日 星期四 10时39分15秒
/////////////////////////////////////////////////////

module  switch_top_v1_tb#(
    parameter    PORT_NUM = 4
)();

reg                         clk;
reg                         rst_n;
reg     [PORT_NUM-1:0]      mii_rx_clk;
reg     [PORT_NUM-1:0]      mii_rx_dv;
reg     [PORT_NUM-1:0][3:0] mii_rxd;
reg     [PORT_NUM-1:0]      mii_tx_clk;

wire    [PORT_NUM-1:0]      mii_tx_en;
wire    [PORT_NUM-1:0][3:0] mii_txd;


always #5 clk = ~clk;
always #20  mii_rx_clk[PORT_NUM-1:0] = ~mii_rx_clk[PORT_NUM-1:0];
always #20  mii_tx_clk[PORT_NUM-1:0] = ~mii_tx_clk[PORT_NUM-1:0];



initial begin
    $fsdbDumpfile("switch_top_v1.fsdb");
    $fsdbDumpvars(0,switch_top_v1_tb);
    $fsdbDumpMDA();

    clk = 1'b0;
    rst_n = 1'b0;
    mii_rx_clk[PORT_NUM-1:0] = 4'b0;
    mii_tx_clk[PORT_NUM-1:0] = 4'b0;
    mii_rx_dv[PORT_NUM-1:0]  = 4'b0;

    for(integer i=0;i<PORT_NUM;i=i+1)
        mii_rxd[i][3:0] = 4'b0;

    repeat(5) @(posedge clk);#0;
    rst_n = 1'b1;
    repeat(2) @(posedge mii_rx_clk[0]);#0;
//从port 1发送一个长度合法的数据帧，crc正确
    frame_trans(        
        4'b0010,
        12'd80,
        4'h5,4'hd,
        48'hf0f1f2f3f4f5,
        48'he0e1e2e3e4e5,
        16'h0800,
        32'h8a7160bd
    );
    repeat(5)@(posedge mii_rx_clk[0]);#0;
//从port 2发送一个超短数据帧，crc正确
    frame_trans(
        4'b0100,
        12'd60,
        4'h5,4'hd,
        48'ha0a1a2a3a4a5,
        48'hb0b1b2b3b4b5,
        16'h0800,
        32'h11645276
    );
    repeat(5)@(posedge mii_rx_clk[0]);#0;
//从port 3发送一个合法数据帧，crc错误
    frame_trans(
        4'b1000,
        12'd80,
        4'h5,4'hd,
        48'ha0a1a2a3a4a5,
        48'hb0b1b2b3b4b5,
        16'h0800,
        32'hc704dd23
    );
    repeat(5)@(posedge mii_rx_clk[0]);#0;
//从port 0发送一个超长数据帧，crc正确
    frame_trans(
        4'b0001,
        12'd1530,
        4'h5,4'hd,
        48'ha0a1a2a3a4a5,
        48'hb0b1b2b3b4b5,
        16'h0800,
        32'hc704dd7b
    );
    repeat(5)@(posedge mii_rx_clk[0]);#0;

    #10000;
    $finish;

end








task    frame_trans();
    input   [3:0]   port_id;
    input   [11:0]  length;
    input   [3:0]   frame_pre;
    input   [3:0]   frame_sfd;
    input   [47:0]  destiny_mac_addr;
    input   [47:0]  source_mac_addr;
    input   [15:0]  frame_type;
    input   [31:0]  fcs;

begin
    mii_rx_dv[3:0] = port_id[3:0];
    for(integer j=0;j<2*length;j=j+1)begin
        for(integer i=0;i<PORT_NUM;i=i+1)begin
            if(port_id[i])begin
                if(j<15)
                    mii_rxd[i][3:0] = frame_pre[3:0];
                else if(j==15)
                    mii_rxd[i][3:0] = frame_sfd[3:0];
                else if(j<28)
                    mii_rxd[i][3:0] = destiny_mac_addr[112-4*j-1-:4];
                else if(j<40)
                    mii_rxd[i][3:0] = source_mac_addr[160-4*j-1-:4];
                else if(j<44)
                    mii_rxd[i][3:0] = frame_type[176-4*j-1-:4];
                else if(j<2*length-8)
                    mii_rxd[i][3:0] = j;
                else 
                    mii_rxd[i][3:0] = fcs[8*length-4*j-1-:4];
            end
            else 
                mii_rxd[i][3:0] = 4'b0;
        end
        @(posedge mii_rx_clk);#0;
    end
    mii_rx_dv[3:0] = 4'b0;
end
endtask


/*
    for(integer i=0;i<PORT_NUM;i=i+1)begin
        if(port_id[i])begin
            for(integer j=0;j<2*length;j=j+1)begin
                if(j<15)
                    mii_rxd[i][3:0] = 4'h5;
                else if(j==15)
                    mii_rxd[i][3:0] = 4'hd;
                else if(j<28)
                    mii_rxd[i][3:0] = destiny_mac_addr[112-4*j-1-:4];
                else if(j<40)
                    mii_rxd[i][3:0] = source_mac_addr[160-4*j-1-:4];
                else if(j<44)
                    mii_rxd[i][3:0] = frame_type[176-4*j-1-:4];
                else if(j<2*length-8)
                    mii_rxd[i][3:0] = j;
                else 
                    mii_rxd[i][3:0] = fcs[4*length-4*j-1-:4];
                @(posedge mii_rx_clk);#0;
            end
            mii_rx_dv[i] = 1'b0;
        end
        else 
            mii_rxd[i][3:0] = 4'b0;
    end
*/
    

switch_top_v1#(
    .PORT_NUM(4)
)
x_switch_top(
    .clk(clk),
    .rst_n(rst_n),
    .mii_rx_clk(mii_rx_clk),
    .mii_rx_dv(mii_rx_dv),
    .mii_rxd(mii_rxd),
    .mii_tx_clk(mii_tx_clk),
    .mii_tx_en(mii_tx_en),
    .mii_txd(mii_txd)
);

endmodule
